package org.moonshiner.controller.security;

import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class DESFileEncryptor extends FileEncryptor {

	public void doCrypt(String password, InputStream in, OutputStream out,
			int cipherMode) {
		DESKeySpec keySpec = getKeySpec(password);

		SecretKeyFactory secretKeyFactory = getSecretKey();

		SecretKey key = getSecretKey(keySpec, secretKeyFactory);

		Cipher cipher = getChiper("DES");

		if (cipherMode == Cipher.ENCRYPT_MODE) {
			try {
				encrypt(in, out, cipherMode, key, cipher);
			} catch (InvalidKeyException e) {
				e.printStackTrace();
			}
		} else if (cipherMode == Cipher.DECRYPT_MODE) {
			try {
				decrypt(in, out, cipherMode, key, cipher);
			} catch (InvalidKeyException e) {
				e.printStackTrace();
			}
		}

	}

	private SecretKey getSecretKey(DESKeySpec keySpec,
			SecretKeyFactory secretKeyFactory) {
		SecretKey key = null;
		try {
			key = secretKeyFactory.generateSecret(keySpec);
		} catch (InvalidKeySpecException e1) {
			e1.printStackTrace();
		}
		return key;
	}

	private SecretKeyFactory getSecretKey() {
		SecretKeyFactory secretKeyFactory = null;
		try {
			secretKeyFactory = SecretKeyFactory.getInstance("DES");
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
		}
		return secretKeyFactory;
	}

	private DESKeySpec getKeySpec(String password) {
		DESKeySpec keySpec = null;
		try {
			keySpec = new DESKeySpec(password.getBytes());
		} catch (InvalidKeyException e1) {
			e1.printStackTrace();
		}
		return keySpec;
	}

	private void decrypt(InputStream in, OutputStream out, int cipherMode,
			SecretKey key, Cipher cipher) throws InvalidKeyException {
		cipher.init(cipherMode, key);
		CipherOutputStream cipherOutputStream = new CipherOutputStream(out,
				cipher);
		doCopy(in, cipherOutputStream);
	}

	private void encrypt(InputStream in, OutputStream out, int cipherMode,
			SecretKey key, Cipher cipher) throws InvalidKeyException {
		cipher.init(cipherMode, key);
		CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
		doCopy(cipherInputStream, out);
	}

}
